package com.chen.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chen.constant.LkdConstant;
import com.chen.mapper.*;
import com.chen.pojo.common.PageResult;
import com.chen.pojo.dto.TaskDetailsDto;
import com.chen.pojo.dto.TaskDto;
import com.chen.pojo.dto.TaskJobDto;
import com.chen.pojo.entry.*;
import com.chen.pojo.vo.TaskReportVo;
import com.chen.pojo.vo.TaskVo;
import com.chen.pojo.vo.TaskWorkVo;
import com.chen.service.TaskService;
import com.chen.utils.CodeUtils;
import com.chen.utils.PageUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author chen
 * @version 1.0
 * @create_date 2025/8/20
 * 任务管理业务实现类
 */
@Service
@Transactional
@RequiredArgsConstructor
public class TaskServiceImpl implements TaskService {
    private final TaskMapper taskMapper;
    private final TaskStatusTypeMapper taskStatusTypeMapper;
    private final TaskTypeMapper taskTypeMapper;
    private final TaskJobMapper taskJobMapper;
    private final UserMapper userMapper;
    private final VendingMachineMapper vendingMachineMapper;
    private final TaskDetailsMapper taskDetailsMapper;
    private final TaskCollectMapper taskCollectMapper;

    /**
     * 工单统计
     *
     * @param start 开始日期
     * @param end   结束日期
     * @return 统计结果
     */
    @Override
    public List<TaskReportVo> getTaskReportInfo(LocalDateTime start, LocalDateTime end) {
        List<TaskReportVo> resultList = new ArrayList<>();
        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(start != null && end != null, Task::getCreateTime, start, end);
        List<Task> tasks = taskMapper.selectList(wrapper);
        if (!CollectionUtils.isEmpty(tasks)) {

            Map<LocalDate, List<Task>> taskMap = tasks.stream().collect(
                    Collectors.groupingBy(s -> s.getCreateTime().toLocalDate()));

            for (Map.Entry<LocalDate, List<Task>> entry : taskMap.entrySet()) {

                TaskReportVo taskReportVo = new TaskReportVo();
                List<Task> values = entry.getValue();
                taskReportVo.setTotal((long) values.size());
                taskReportVo.setData(entry.getKey());

                // 我理解为如果区间内存在数据，不用修复，否则要修复
                taskReportVo.setRepair(true);
                if (!CollectionUtils.isEmpty(values)) {
                    // 统计已完成
                    taskReportVo.setCompletedTotal(values.stream()
                            .filter(s -> LkdConstant.COMPLETED.equals(s.getTaskStatus())).count());
                    // 统计已取消
                    taskReportVo.setCancelTotal(values.stream()
                            .filter(s -> LkdConstant.CANCEL.equals(s.getTaskStatus())).count());
                    // 统计进行中
                    taskReportVo.setProgressTotal(values.stream()
                            .filter(s -> LkdConstant.PROGRESS.equals(s.getTaskStatus())).count());
                    // 统计代办
                    taskReportVo.setWorkerCount(values.stream()
                            .filter(s -> LkdConstant.WORKER.equals(s.getTaskStatus())).count());
                    taskReportVo.setRepair(false);
                }
                resultList.add(taskReportVo);
            }

        }
        return resultList;
    }

    /**
     * 获取售货机维修次数
     *
     * @param start     开始日期
     * @param end       接收日期
     * @param innerCode 售货机编号
     * @return 维修次数
     */
    @Override
    public Long getRepairCount(LocalDate start, LocalDate end, String innerCode) {
        return taskMapper.selectRepairCount(start, end, innerCode);
    }

    /**
     * 工单搜索
     *
     * @param pageIndex 起始页
     * @param pageSize  页大小
     * @param taskCode  任务编号
     * @param status    任务状态
     * @param isRepair  是否是维修工单
     * @return 搜索结果
     */
    @Override
    public PageResult<TaskVo> searchList(Integer pageIndex, Integer pageSize,
                                         String taskCode, Integer status, Boolean isRepair) {
        Integer repair = Boolean.TRUE.equals(isRepair) ? 1 : 0;
        Page<TaskVo> page = new Page<>(pageIndex, pageSize);
        page = taskMapper.selectTaskList(page, taskCode, status, repair);
        return PageUtils.mapperResult(page);
    }

    /**
     * 获取所有工单状态
     *
     * @return 结果
     */
    @Override
    public List<TaskStatusType> getAllTaskStatus() {
        return taskStatusTypeMapper.selectList(null);
    }

    @Override
    public List<TaskType> getAllTaskType() {
        return taskTypeMapper.selectList(null);
    }

    @Override
    public TaskVo getTaskInfoById(String taskId) {
        return taskMapper.selectTaskInfoById(taskId);
    }

    @Override
    public Boolean autoSupplyConfig(TaskJobDto taskJobDto) {
        TaskJob taskJob = new TaskJob();
        LambdaQueryWrapper<TaskJob> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskJob::getAlertValue, taskJobDto.getAlertValue());
        TaskJob result = taskJobMapper.selectOne(wrapper);
        if (Objects.nonNull(result)) {
            taskJob.setId(result.getId());
            taskJob.setAlertValue(taskJobDto.getAlertValue());
            taskJobMapper.updateById(taskJob);
        } else {
            taskJob.setAlertValue(taskJobDto.getAlertValue());
            taskJobMapper.insert(taskJob);
        }
        return true;
    }

    @Override
    public Integer supplyAlertValue() {
        TaskJob taskJob = taskJobMapper.selectOne(null);
        return taskJob.getAlertValue();
    }

    @Override
    public Boolean addTask(TaskDto taskDto) {
        Task task = new Task();
        // 工单编号
        task.setTaskCode(CodeUtils.getTaskCode());
        // 创建类型
        task.setCreateType(taskDto.getCreateType());
        // 工单状态:待办
        task.setTaskStatus(LkdConstant.WORKER);
        // 设备编号
        task.setInnerCode(taskDto.getInnerCode());
        // 指派人id
        task.setAssignorId(taskDto.getAssignorId());
        // 工单类型
        task.setProductTypeId(taskDto.getProductType());
        // 时间
        task.setCreateTime(LocalDateTime.now());
        task.setUpdateTime(LocalDateTime.now());
        // 描述
        task.setDescription(taskDto.getDesc());
        // 执行人信息
        User user = userMapper.selectById(taskDto.getUserId());
        task.setUserId(user.getId());
        task.setUserName(user.getUserName());

        // 区域id
        Node node = vendingMachineMapper.selectNodeInfoByInnerCode(taskDto.getInnerCode());
        task.setRegionId(node.getRegionId());
        task.setAddr(node.getAddr());

        taskMapper.insert(task);
        List<TaskDetailsDto> details = taskDto.getDetails();
        if (!CollectionUtils.isEmpty(details)) {
            TaskDetails taskDetails = new TaskDetails();
            BeanUtils.copyProperties(details, taskDetails);
            taskDetailsMapper.insert(taskDetails);
        }
        return true;
    }

    @Override
    public List<TaskDetails> getTaskDetails(String taskId) {
        LambdaQueryWrapper<TaskDetails> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TaskDetails::getTaskId, taskId);
        return taskDetailsMapper.selectList(wrapper);
    }

    @Override
    public Boolean cancelTaskById(String taskId) {
        Task task = taskMapper.selectById(taskId);
        task.setTaskStatus(LkdConstant.CANCEL);
        taskMapper.updateById(task);
        return true;
    }

    @Override
    public List<TaskCollect> collectReport(LocalDate start, LocalDate end) {
        LambdaQueryWrapper<TaskCollect> wrapper = new LambdaQueryWrapper<>();
        wrapper.between(start != null && end != null, TaskCollect::getCollectDate, start, end);
        return taskCollectMapper.selectList(wrapper);
    }

    @Override
    public List<TaskWorkVo> getUserWorkTop10(LocalDate start, LocalDate end, Boolean isRepair, String regionId) {
        Integer repair = Boolean.TRUE.equals(isRepair) ? 1 : 0;
        regionId = "0".equals(regionId) ? null : regionId;
        return taskMapper.selectUserWorkTop10(start, end, repair, regionId);
    }

    @Override
    public TaskWorkVo getUserWork(Integer userId, LocalDateTime start, LocalDateTime end) {
        return taskMapper.selectUserWork(userId, start, end);
    }
}
